using UnityEngine; using wildlogicgames; using Uniarts.ColorCorrection; namespace RebelHeartEclipse { public enum CameraBehaviour { DefaultStandby = -1, CircleAroundPivot = 0, MaintainLockedAngle = 1, IsometricToCharacter = 2, ShakeView = 3, }; public enum IsometricAngle { NorthEast, NorthWest, SouthEast, SouthWest } public class CameraController : MonoBehaviour { [Header("--------------------BATTLE GROUND GRIDGEN PLUGIN")] [Header("Plugin the grid generator here.")] [SerializeField] public BattleGroundGridGenerator _battleGroundGridGenerator; [Header("--------------------UI MANAGER PLUGIN")] [Header("Plugin the UI manager here.")] [SerializeField] public UIManager _UIManager; [Header("--------------------SQUAD MANAGER PLUGIN")] [Header("Plugin the squad manager here.")] [SerializeField] public SquadManager _squadManager; [Header("--------------------CHARACTER ACTION STAGE PLUGIN")] [Header("Plugin the character action stage here.")] [SerializeField] public CharacterActionStage _characterActionStage; [Header("--------------------CURSOR OBJ PLUGIN")] [SerializeField] public CursorObj _cursorObj; private ColorCorrectionPro _camFilter; private Transform _transform; private float _moveSpeed = 1.0f; private Vector3 _targetMovePosition; private CharacterObj _characterObj; private int _x, _y; private const float _maxFOV = 32.0f;//28.0f;//32.0f;//44.0f;//70.0f; private const float _zoomFreq = 0.25f;///0.05f;//0.1f; private bool _process, _processCamBehaviour; private const float _baseTimeSpeed = 10.0f;//4.0f; private const float _orbitSpeed = 75.0f;//50.0f;//25f; private const float _tiltSpeed = 1.0f; private Vector3 _orbitAxis = Vector3.up; private Vector3 _pivotPoint, _prevPivotPoint; private Vector3 _eulerAngleLock; private float _shakeDuration = 0f; private float _shakeMagnitude = 0.2f; private Vector3 _originalCamPos; private CameraBehaviour _cameraBehaviour; public IsometricAngle _isometricAngleState; private GameObject[] _timerObj = new GameObject[4]; private WTimer[] _timer = new WTimer[4]; private float _waitime = 0.1f;//0.25f; private bool _inputLocked, _camJourneyLocked; private void Awake() => Setup(); private void Start() { } private void Setup() { _transform = this.transform; _eulerAngleLock = _transform.eulerAngles; _eulerAngleLock.x = 40.0f; _eulerAngleLock.y = 45.0f; _process = true; _processCamBehaviour = true; _camJourneyLocked = false; _cameraBehaviour = CameraBehaviour.DefaultStandby; _isometricAngleState = IsometricAngle.SouthWest; Camera.main.fieldOfView = _maxFOV; _cursorObj.EnableCursor(); _camFilter = this.gameObject.GetComponent(); //_battleGroundGridGenerator.InitGeneration(); //Script order, call before camera. _pivotPoint = _battleGroundGridGenerator.GetCenterGridPosition(); for (int i = 0; i < _timerObj.Length; i++) { _timerObj[i] = new GameObject(); _timerObj[i].AddComponent(); _timer[i] = _timerObj[i].GetComponent(); _timer[i].Reset(); _timer[i].StartTimer(_waitime); } _inputLocked = false; } public Vector3 GetPivotPoint() => _pivotPoint; public void SetPivotPoint(Vector3 v) => _pivotPoint = v; public void ApplyIsomViewType(int x, int y, CameraBehaviour cameraBehaviour) { _transform.eulerAngles = _eulerAngleLock; _pivotPoint = _battleGroundGridGenerator.GetSpecifiedCellPosition(x, y); _transform.LookAt(_pivotPoint); _cameraBehaviour = cameraBehaviour;// CameraBehaviour.CircleAroundPivot; } private void Update() { if (!_process) return; CameraBehaviourUpdate(); DetectViewToGridClickUpdate(); } private void DetectViewToGridClickUpdate() { if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Idle_Player_Attack) return; if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Process_Player_Attack) return; if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Update_UI_Status) return; if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Process_Player_Move) return; if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Completed_Player_Move) return; if (_inputLocked) return; if (_cursorObj.GetMouseFirstClick()) { float cellWidth = _battleGroundGridGenerator.GetCellWidth(); Vector3 v = _battleGroundGridGenerator.GetGridStartPosition() - new Vector3(cellWidth / 2f, 0f, cellWidth / 2f); Plane plane = new Plane(Vector3.up, v); // flat on XZ Ray ray = Camera.main.ScreenPointToRay(_cursorObj.GetMousePosition()); if (plane.Raycast(ray, out float enter)) { Vector3 hitPoint = ray.GetPoint(enter); Vector3 relativeClickPos = hitPoint - v; int clickX = Mathf.FloorToInt(relativeClickPos.x / cellWidth); int clickY = Mathf.FloorToInt(relativeClickPos.z / cellWidth); // Assuming grid is laid on XZ plane if (clickX >= 0 && clickX < _battleGroundGridGenerator.GetGridCellTotalX() && clickY >= 0 && clickY < _battleGroundGridGenerator.GetGridCellTotalY()) { _characterActionStage.ProcessGridToViewClickReport(clickX, clickY); } } } if (_cursorObj.GetMouseMiddleClick()) { } } private void CameraBehaviourUpdate() { if (!_processCamBehaviour) return; float horizontalInput = 0f; switch (_cameraBehaviour) { case CameraBehaviour.MaintainLockedAngle: ; LockedIsometricViewUpdate(); break; case CameraBehaviour.CircleAroundPivot: horizontalInput = (Time.deltaTime * (_baseTimeSpeed / 1f)); _transform.RotateAround(_pivotPoint, _orbitAxis, _orbitSpeed * horizontalInput * Time.deltaTime); break; case CameraBehaviour.IsometricToCharacter: IsometricToCharacterView(); break; case CameraBehaviour.ShakeView: if (_shakeDuration > 0) { float x = Random.Range(-1f, 1f) * _shakeMagnitude; float y = Random.Range(-1f, 1f) * _shakeMagnitude; _transform.localPosition = _originalCamPos + new Vector3(x, y, 0f); _shakeDuration -= Time.deltaTime; } else { _transform.localPosition = _originalCamPos; _cameraBehaviour = CameraBehaviour.MaintainLockedAngle; if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Process_Player_Attack) _cameraBehaviour = CameraBehaviour.IsometricToCharacter; if (EventManager.GetEventFlag() == EventFlagID.EventFlag_Update_UI_Status) _cameraBehaviour = CameraBehaviour.IsometricToCharacter; } break; } } public void LockedIsometricViewUpdate() { Vector3 dir = Vector3.zero; switch (_isometricAngleState) { case IsometricAngle.NorthEast: dir = new Vector3(1, 1, -1).normalized; break; case IsometricAngle.NorthWest: dir = new Vector3(-1, 1, -1).normalized; break; case IsometricAngle.SouthEast: dir = new Vector3(1, 1, 1).normalized; break; case IsometricAngle.SouthWest: dir = new Vector3(-1, 1, 1).normalized; break; } //Pos relative to target from camera. Vector3 focusPoint = _pivotPoint; _transform.position = focusPoint + dir * 6.6f; _transform.position = new Vector3(_transform.position.x, 6.6f, _transform.position.z); _transform.LookAt(focusPoint); } private void IsometricToCharacterView() { //if (_camJourneyLocked) return; //Isometric to start with. Vector3 startDir = Vector3.zero; switch (_isometricAngleState) { case IsometricAngle.NorthEast: startDir = new Vector3(1, 1, -1).normalized; break; case IsometricAngle.NorthWest: startDir = new Vector3(-1, 1, -1).normalized; break; case IsometricAngle.SouthEast: startDir = new Vector3(1, 1, 1).normalized; break; case IsometricAngle.SouthWest: startDir = new Vector3(-1, 1, 1).normalized; break; } //LockedIsometricViewUpdate(); //target direction = side view Vector3 sideDir = new Vector3(0, 0, -1).normalized; // nterpolation factor [0..1] float result = 0f; result = Mathf.Clamp01(result + Time.deltaTime * 1.0f); //smoothly interpolate between start and side Vector3 dir = Vector3.Slerp(startDir, sideDir, result); //maintain distance Vector3 focusPoint = _pivotPoint; //_transform.position = focusPoint + dir * 6.6f; focusPoint = focusPoint + dir * 4.4f;// 6.6f; //_transform.LookAt(focusPoint); _transform.position = Vector3.MoveTowards(_transform.position, focusPoint, (_moveSpeed*4) * Time.deltaTime); _transform.LookAt(_pivotPoint); if (Vector3.Distance(_transform.position, focusPoint) < 0.01f) { if (_camJourneyLocked) return; int x = EventManager.GetCurrentPlayerCellX(); int y = EventManager.GetCurrentPlayerCellY(); //x = _squadManager.GetCurrentPlayerObj().GetAssignedGridX(); //y = _squadManager.GetCurrentPlayerObj().GetAssignedGridY(); CharacterClass characterClass = _squadManager.GetCurrentPlayerObj().GetCharacterStat()._characterClass; _battleGroundGridGenerator.DeactivateAttackableCells(x, y, characterClass); _UIManager.DisableBattleUIWindow(); _camJourneyLocked = true; _timer[1].Reset(); if (_characterObj == null) return; //if (_characterObj.GetCharacterStat() == null) return; if (_characterObj.GetCharacterStat()._characterClass != CharacterClass.Bowman) { //_timer[1].Reset(); _timer[1].StartTimer(0.1f); } return; //print("ping"); //InitShakeFX(); } } public void InitShakeFX(float duration = 0.5f, float magnitude = 0.1f) { _shakeDuration = duration; _shakeMagnitude = magnitude; _originalCamPos = _transform.localPosition; _cameraBehaviour = CameraBehaviour.ShakeView; CameraBehaviourUpdate(); } public void EnabledInputLock() => _inputLocked = true; public void DisableInputLock() => _inputLocked = false; public bool IsInputLocked() => _inputLocked; public void EnabledCameraJounreyLock() => _camJourneyLocked = true; public void DisableCameraJounreyLock() => _camJourneyLocked = false; public bool IsCameraJounreyLocked() => _camJourneyLocked; public void EnabledCameraBehaviour() => _processCamBehaviour = true; public void DisableCameraBehaviour() => _processCamBehaviour = false; public bool IsCameraBehaviourEnabled() => _processCamBehaviour; public void ResetCamFilterUpdate() { if (EventManager.GetEventFlag() != EventFlagID.EventFlag_Idle) return; if (_camFilter.brightness != 0) _camFilter.brightness = 0; if (_camFilter.sharpness != 0) _camFilter.sharpness = 0; } public void ApplyCamFilter(int i) { switch(i) { case 0: if (_camFilter.brightness != -100) _camFilter.brightness = -100; if (_camFilter.sharpness != -44) _camFilter.sharpness = -44; break; case 1: if (_camFilter.brightness != 0) _camFilter.brightness = 0; if (_camFilter.sharpness != 0) _camFilter.sharpness = 0; break; } } public void SetBehaviour(CameraBehaviour cameraBehaviour) { _cameraBehaviour = cameraBehaviour; } } }